/*
 *  Computer Graphics:  Andrew Hanson
 * GLUT RGB  Graphics template 
 *

 cc -o glut.linux glut.c  -lglut -lGLU -lGL  -lm


 NOTE: This should work on default-X-configured Linux GRAPHICS SERVERS
        because it defines an RGB visual. 

 *
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>

/* Local Graphics Definitions  */
#include "defs.h"


/***************************************************************/
/******************** MY GLOBAL VARIABLES **********************/
/***************************************************************/

int mouseButtons = 0;

int MouseModifiers = 0;

int  X=0, Y=0, dX=0, dY=0;
GLfloat XC = 0.0, YC = 0.0, ZC = -10.0;
int main_window;
int main_height, main_width;

/***************************************************************/
/*********************** MOUSE CALLBACKS ***********************/
/***************************************************************/

/* Mouse Button  UP/DOWN  or DOWN/UP transition only */
void
mouse(int button, int state, int x, int y)
{
  X = x;
  Y =  main_height - y - 1;	/* Invert to right-handed system */
  button = (1 << button);
  
  MouseModifiers = glutGetModifiers();
  /* bitmask with GLUT_ACTIVE_SHIFT, GLUT_ACTIVE_CTRL, GLUT_ACTIVE_ALT */

  if (state == GLUT_DOWN)
    mouseButtons |= button;
  else
    mouseButtons &= (~(button));

     
  fprintf(stderr,"Comment this out: mouse buttons = [%d], modifiers = [%d] \n\
          state = %s, mouse at (%d,%d)\n",
	  mouseButtons, MouseModifiers, 
          state == GLUT_UP? "Just Up":"Just Down",x,y); 
 
  glutPostRedisplay(); 
}

/* Mouse motion WHILE BUTTON DOWN  */
/*  COMPLAINS  if you call glutGetModifiers()  here!! */
void
motion(int x, int y)
{
  fprintf(stderr,"Comment this out: mouse at (%d,%d)\n\
          mouse buttons = [%d], modifiers = [%d]\n",
	  x,y, mouseButtons, MouseModifiers);  
  X = x;
  Y =  main_height - y - 1;	/* Invert to right-handed system */


  switch(mouseButtons ){
  case 0x1:  /* Left Mouse Button   */
    break;
  case 0x2:  /* Middle Mouse Button */
    break;
  case 0x4:  /* Right Mouse Button  */
    break;
  }
  glutPostRedisplay();

}

/* Mouse motion WHILE ALL BUTTONS UP  */
/*  COMPLAINS  if you call glutGetModifiers()  here!! */
void
passive(int x, int y)
{
  X = x;
  Y = main_height - y - 1;

  /*  glutPostRedisplay(); */
}

/* Handle Keyboard */
void
keyboard(unsigned char key, int x, int y)
{
  /*  Option: To force all lower case */
  /* if (key >= 'A' && key <= 'Z') key = (key-'A') + 'a'; */

  switch (key) {
    
  case 'q' : case 27 :  /* 27 -> ESC */
    fprintf(stderr,"Normal Exit.\n");
    exit(EXIT_SUCCESS);
    break;
  default: fprintf(stderr,"Unhandled key: %c [%d] \n",key,key);
  }

  glutPostRedisplay();
}


/***************************************************************/
/************************** INIT GL ****************************/
/***************************************************************/


void
initGL()
{
  glClearColor(0.0,1.0,1.0,1.0);
  glEnable(GL_DEPTH_TEST);
}




/***************************************************************/
/************************ DRAW STUFF ***************************/
/***************************************************************/

void
drawObjs()
{
  glColor3f(1.0,1.0,0.0);
  glLineWidth(3.0);
  
  glBegin(GL_LINES);
  glVertex2f(0.0,0.0);
  glVertex2f(100.0,100.0);
  glEnd();

}




/***************************************************************/
/************************ GLUT STUFF ***************************/
/***************************************************************/


void
reshape(int w, int h)
{
  fprintf(stderr,"Comment this out: reshape \n");
  w = Max(w,128);
  h = Max(h,128);
  main_height = h;
  main_width = w;
  glutReshapeWindow(w,h);
  glViewport(0,0,w,h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
   gluOrtho2D(0.0,(double)Max(w,200), (double)Max(h,200), 0.0);  
   /*  gluOrtho2D(0.0,(double)Max(w,200), 0.0, (double)Max(h,200));  */

  /*  glFrustum(-1.0,1.0,-1.0,1.0,5.0,25.0);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslatef(XC,YC,ZC);
  */

  glMatrixMode(GL_MODELVIEW);
}

void
visibility(int state)
{
  /* May also want to check PARTIAL DAMAGE that
     does not result in a call to the visibility callback:
      if (glutLayerGet(GLUT_NORMAL_DAMAGED)) {
       redraw = TRUE; }
       */
  fprintf(stderr,"Comment this out: visibility: %s\n",
	  (state==GLUT_VISIBLE)?"visible":"invisible");
  if (state == GLUT_VISIBLE){
    glutPostRedisplay();
  }
}

void
display(void)
{
  fprintf(stderr,"Comment this out: display\n");

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  /* glClear(GL_COLOR_BUFFER_BIT); */

  drawObjs();

  glutSwapBuffers();
}



/***************************************************************/
/**************************** MAIN *****************************/
/***************************************************************/


int
main(int argc, char **argv)
{
  /* GLUT Initialization */
  glutInit(&argc,argv);
  glutInitWindowSize(300, 300);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA |GLUT_DEPTH);

  /* Create a new window and give a title to it */
  main_window = glutCreateWindow("CHANGE THIS TITLE!!!!!!!");

  /* Initialize OpenGL stuff */
  initGL();

  /* Post Event Handlers */
  glutReshapeFunc(reshape);
  glutVisibilityFunc(visibility);
  glutDisplayFunc(display);
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  glutPassiveMotionFunc(passive);
    
  glutKeyboardFunc(keyboard);
  fprintf(stderr,"Press ESC or 'q' to Exit.\n");

  glutIdleFunc(NULL);

  glutMainLoop();

  return(EXIT_SUCCESS);
}
